#include "io/rotating_file_writer.hpp"
#include <iostream>
#include <system_error>

namespace axon_logger {
namespace io {

RotatingFileWriter::RotatingFileWriter(const std::string& base_filename, size_t max_file_size, size_t max_files)
    : m_baseFilePath(base_filename)
    , m_maxFileSize(max_file_size)
    , m_maxFiles(max_files > 0 ? max_files : 1)  // 至少保留一个备份文件
    , m_currentFileSize(0) {
    // 确保文件目录存在
    if (m_baseFilePath.has_parent_path()) {
        try {
            std::filesystem::create_directories(m_baseFilePath.parent_path());
        } catch (const std::filesystem::filesystem_error& e) {
            std::cerr << "Error creating log directory: " << e.what() << std::endl;
        }
    }
    open_file();
}


RotatingFileWriter::~RotatingFileWriter() {
    if (m_fileStream.is_open()) {
        m_fileStream.close();
    }
}


void RotatingFileWriter::open_file() {
    m_fileStream.open(m_baseFilePath, std::ios::app);  // 追加模式打开
    if (!m_fileStream.is_open()) {
        std::cerr << "Error: Failed to open log file: " << m_baseFilePath << std::endl;
        return;
    }
    // 获取当前文件大小
    m_fileStream.seekp(0, std::ios::end);
    m_currentFileSize = m_fileStream.tellp();
}


void RotatingFileWriter::write(std::string_view message) {
    std::lock_guard<std::mutex> lock(m_mutex);

    if (!m_fileStream.is_open()) {
        return; // 文件未打开，日志丢失
    }

    size_t message_size = message.length() + 1;  // 给新行留空间
    if (m_currentFileSize + message_size > m_maxFileSize) {
        rotate();
    }

    m_fileStream.write(message.data(), message.length());
    m_fileStream.put('\n');
    m_fileStream.flush();  // 确保日志写入磁盘
    m_currentFileSize += message_size;
}


void RotatingFileWriter::rotate() {
    // 关闭当前文件
    m_fileStream.close();

    // 生成文件名模板
    std::string stem = m_baseFilePath.stem().string();
    std::string ext = m_baseFilePath.extension().string();

    // 删除最旧的日志文件
    std::filesystem::path oldest_log = m_baseFilePath.parent_path() / (stem + "." + std::to_string(m_maxFiles) + ext);
    if (std::filesystem::exists(oldest_log)) {
        try {
            std::filesystem::remove(oldest_log);
        } catch(const std::filesystem::filesystem_error& e) {
            std::cerr << "Error removing oldest log file: " << e.what() << std::endl;
        }
    }

    // 重命名旧文件 (从后往前， app.4.log --> app.5.log)
    for (size_t i = m_maxFiles - 1; i >= 1; --i) {
        std::filesystem::path src = m_baseFilePath.parent_path() / (stem + "." + std::to_string(i) + ext);
        std::filesystem::path dest = m_baseFilePath.parent_path() / (stem + "." + std::to_string(i + 1) + ext);
        if (std::filesystem::exists(src)) {
            try {
                std::filesystem::rename(src, dest);
            } catch (const std::filesystem::filesystem_error& e) {
                std::cerr << "Error renaming log file from " << src << " to " << dest << ": " << e.what() << std::endl;
            }
        }
    }

    // 重命名当前已满的日志文件
    std::filesystem::path first_backup = m_baseFilePath.parent_path() / (stem + ".1" + ext);
    if (std::filesystem::exists(m_baseFilePath)) {
        try {
            std::filesystem::rename(m_baseFilePath, first_backup);
        } catch (const std::filesystem::filesystem_error& e) {
            std::cerr << "Error renaming current log file to " << first_backup << ": " << e.what() << std::endl;
        }
    }

    // 重新打开一个新的日志文件并重置大小计数器
    open_file();
}
}  // namespace io
}  // namespace axon_logger
